`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: CBICR, Tsinghua Univ.
// Engineer: Hongyi Li
// 
// Create Date: 2024/12/23 11:58:54
// Design Name: 
// Module Name: Virtual Channel Allocation
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module VcMux
#(
    parameter DataWidth = 'd32,
    parameter VCNumber  = 'd4
)(
    input  [DataWidth*VCNumber   -1:0]     i_data_e,
    input  [DataWidth*VCNumber   -1:0]     i_data_w,
    input  [DataWidth*VCNumber   -1:0]     i_data_n,
    input  [DataWidth*VCNumber   -1:0]     i_data_s,
    input  [DataWidth*VCNumber   -1:0]     i_data_l,

    input  [VCNumber*5           -1:0]     i_winner,
    
    output [DataWidth            -1:0]     o_data_e,
    output [DataWidth            -1:0]     o_data_w,
    output [DataWidth            -1:0]     o_data_n,
    output [DataWidth            -1:0]     o_data_s,
    output [DataWidth            -1:0]     o_data_l
);

// Select the Winner Virtual-Channel
// Input: 
//      - bw_data[i] (VCNumber * {DataWidth}) -> swap_bw_data (DataWidth * {VCNumber})
//      - va_winner (5 * {VCNumber})
// Output:
//      - sel_data_array[i] (DataWidth)
wire [VCNumber * DataWidth         -1:0]      bw_data          [0:4];
wire [DataWidth                    -1:0]      sel_data_array   [0:4];
wire [VCNumber                     -1:0]      swap_bw_data     [0:4][0:(DataWidth-1)];

genvar i, j, k; 
generate
    for (i = 0; i < 5; i = i + 1) begin // i: directions
        for (k = 0; k < DataWidth; k = k + 1) begin // k: DataWidth
            for (j = 0; j < VCNumber; j = j + 1) begin // j: virtual channels
                assign swap_bw_data[i][k][j] = bw_data[i][j*DataWidth+k];
            end
            assign sel_data_array[i][k] = | (swap_bw_data[i][k] & i_winner[VCNumber*(i+1)-1 : i*VCNumber]);
        end
    end
endgenerate

assign bw_data[0] = i_data_e;
assign bw_data[1] = i_data_w;
assign bw_data[2] = i_data_n;
assign bw_data[3] = i_data_s;
assign bw_data[4] = i_data_l;

assign o_data_e = sel_data_array[0];
assign o_data_w = sel_data_array[1];
assign o_data_n = sel_data_array[2];
assign o_data_s = sel_data_array[3];
assign o_data_l = sel_data_array[4];

endmodule